





#include "arch.h"
#include "A.utilities"

//user program



class Root_proc: public Thread{

   public:

        Root_proc()
                : Thread((Tmf0_ptr)&Root_proc::body){}

        void body(){

            fprintf(Sdf::trace, "node %d, in Root_proc::starts\n", Sdf::PROC_ID);
            fflush(Sdf::trace);

            int sendarray[2*3];
            int rbuf[2];

            MPI_Datatype stype;
            int *displs;
            int i;
            int *rcounts;

            #define STRIDE 12
//          rbuf = (int *)malloc(Sdf::PROC_NB*STRIDE*sizeof(int));
            displs = (int *)malloc(Sdf::PROC_NB*sizeof(int));
            rcounts = (int *)malloc(Sdf::PROC_NB*sizeof(int));
            for(i=0; i<Sdf::PROC_NB; i++){
               displs[i] = i*STRIDE;
               rcounts[i] = 3;
            }

            sendarray[0] = 10;
            sendarray[1] = 11;
            sendarray[2] = 12;
            sendarray[3] = 20;
            sendarray[4] = 21;
            sendarray[5] = 22;

              //2 integers separated by 2 integers
            MPI_Type_vector(2, 1, 3, MPI_INT, &stype);
            MPI_Type_commit(&stype);
            MPI_Status status;

            long extent;
            MPI_Type_extent(stype, &extent);

            fprintf(Sdf::trace, "node %d, @@@@1 extent=%d\n", 
                    Sdf::PROC_ID, extent);
            fflush(Sdf::trace);

            int pack_size;
            MPI_Pack_size(1, stype, 
                          MPI_COMM_WORLD, &pack_size);

            int i2_pack_size;
            MPI_Pack_size(2, MPI_INT, 
                          MPI_COMM_WORLD, &i2_pack_size);

            fprintf(Sdf::trace, "node %d, @@@@2 pack_size=%d, i2_pack_size=%d\n", 
                    Sdf::PROC_ID, pack_size, i2_pack_size);
            fflush(Sdf::trace);

            char *pack_res = new char[pack_size];
            ((int *)pack_res)[0]=88, ((int *)pack_res)[1]=89,
            ((int *)pack_res)[2]=90, ((int *)pack_res)[3]=91,
            ((int *)pack_res)[4]=92, ((int *)pack_res)[5]=93;

            char *pack_recv = new char[pack_size];
            ((int *)pack_recv)[0]=78, ((int *)pack_recv)[1]=79,
            ((int *)pack_recv)[2]=80, ((int *)pack_recv)[3]=81,
            ((int *)pack_recv)[4]=82, ((int *)pack_recv)[5]=83;

            int position = 0;
            MPI_Pack(sendarray, 1, stype,
                     pack_res, pack_size, &position, MPI_COMM_WORLD);

            fprintf(Sdf::trace, "node %d, @@@@3 pack_res=%d, %d, %d, %d, %d, %d\n", 
                    Sdf::PROC_ID, 
                    ((int *)pack_res)[0], ((int *)pack_res)[1],
                    ((int *)pack_res)[2], ((int *)pack_res)[3],
                    ((int *)pack_res)[4], ((int *)pack_res)[5]);
            fflush(Sdf::trace);

            int unpack_res[6] = {77, 77, 77, 77, 77, 77};

            fprintf(Sdf::trace, "node %d, @@@@4 unpack_res=%d, %d, %d, %d, %d, %d\n", 
                    Sdf::PROC_ID, 
                    unpack_res[0], unpack_res[1],
                    unpack_res[2], unpack_res[3],
                    unpack_res[4], unpack_res[5]);
            fflush(Sdf::trace);

            int unpack_recv[6] = {77, 77, 77, 77, 77, 77};

            position = 0;
            MPI_Unpack(pack_res, pack_size, &position, 
                       unpack_res, 1, stype,
                       MPI_COMM_WORLD);

            fprintf(Sdf::trace, "node %d, @@@@5 unpack_res=%d, %d, %d, %d, %d, %d\n", 
                    Sdf::PROC_ID, 
                    unpack_res[0], unpack_res[1],
                    unpack_res[2], unpack_res[3],
                    unpack_res[4], unpack_res[5]);
            fflush(Sdf::trace);


            if(!Sdf::PROC_ID){
               MPI_Send(unpack_res, 1, stype, 1, 0, MPI_COMM_WORLD);
               MPI_Send(pack_res, pack_size, MPI_PACKED, 1, 0, MPI_COMM_WORLD);
//               MPI_Send(sendarray, pack_size, stype, 1, 0, MPI_COMM_WORLD);
//               MPI_Send(sendarray, 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
            }else{
               MPI_Recv(rbuf, 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
               MPI_Recv(pack_recv, pack_size, MPI_PACKED, 0, 0, MPI_COMM_WORLD, &status);
               int unpack_res[6] = {77, 77, 77, 77, 77, 77};
               position = 0;
               MPI_Unpack(pack_recv, pack_size, &position, 
                          unpack_recv, 1, stype,
                          MPI_COMM_WORLD);
            }
            if(Sdf::PROC_ID){
               fprintf(Sdf::trace, "node %d, ####1 result=%d,%d\n", 
                       Sdf::PROC_ID, rbuf[0],rbuf[1]);
               fflush(Sdf::trace);

               fprintf(Sdf::trace, "node %d, ####2 pack_recv=%d, %d, %d, %d, %d, %d\n", 
                       Sdf::PROC_ID, 
                       ((int *)pack_recv)[0], ((int *)pack_recv)[1],
                       ((int *)pack_recv)[2], ((int *)pack_recv)[3],
                       ((int *)pack_recv)[4], ((int *)pack_recv)[5]);
               fflush(Sdf::trace);

               fprintf(Sdf::trace, "node %d, ####3 unpack_recv=%d, %d, %d, %d, %d, %d\n", 
                       Sdf::PROC_ID, 
                       unpack_recv[0], unpack_recv[1],
                       unpack_recv[2], unpack_recv[3],
                       unpack_recv[4], unpack_recv[5]);
               fflush(Sdf::trace);
            }

            fprintf(Sdf::trace, "node %d, in Root_proc::finishes\n", Sdf::PROC_ID);
            fflush(Sdf::trace);
        }
};
//end of user program

MAIN(Root_proc, Sdf::empty, Sdf::empty, Sdf::empty)

